package jwtauth

import (
	"encoding/json"
	"errors"
	"github.com/dgrijalva/jwt-go"
	"strings"
)

type JwtTokenHandler struct {
	SecretKey string
}

func NewJwtTokenHandler(secret string) *JwtTokenHandler {
	return &JwtTokenHandler{
		SecretKey: secret,
	}
}

func (h *JwtTokenHandler) GetToken(data interface{}) (string, error) {
	secret := h.SecretKey

	jUser, err := json.Marshal(data)
	if err != nil {
		return "", err
	}
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
		"data": string(jUser),
	})

	return token.SignedString([]byte(secret))
}

func (h *JwtTokenHandler) ParseToken(data interface{}, token string) error {
	secret := h.SecretKey

	if token == "" {
		return errors.New("token empty")
	}

	jwtToken, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
		return []byte(secret), nil
	})

	if err != nil {
		return errors.New("parse token fail:" + err.Error())
	}

	claims, ok := jwtToken.Claims.(jwt.MapClaims)
	if !(ok && jwtToken.Valid) {
		return errors.New("token invalid")
	}

	claimsData := claims["data"]

	dataStr, ok := claimsData.(string)
	if !ok {
		return errors.New("token error")
	}

	//防止出现科学计数的数字
	decoder := json.NewDecoder(strings.NewReader(dataStr))
	decoder.UseNumber()
	err = decoder.Decode(data)
	if err != nil {
		return errors.New("parse data fail:" + err.Error())
	}

	return nil
}
